package org.hdl.anima.session;

import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.hdl.anima.AppConf;
import org.hdl.anima.Application;
import org.hdl.anima.transport.ChannelHandler;
import org.hdl.anima.transport.RemoteException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * @author qiuhd
 * @since  2014年8月15日
 */
public class BackendSession implements ISession {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(BackendSession.class);
	
	public static final int STATUS_CLOSED = -1;
	
	public static final int STATUS_CONNECTED = 1;
	
	public static final int CONNECTED = 1;
	
	public static final int CLOSED = 2;

	private int identity;
	/**
	 * 会话所在服务器Id
	 */
	private String serverId;
	/**
	 * session close listener
	 */
	private SessionCloseListener listener;
	
	private final InetSocketAddress remoteAddress;
	
	private final InetSocketAddress localAddress;
	
	private volatile int status = CONNECTED ;
	
	private final Application application;
	
	private String clientType;
	
	/** 
	 * Attribute map
	 */
	private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
	
	public BackendSession(Application application, String serverId,
			int identity, String remoteAddress, int remotePort,
			String localAddress, int localPort) {
		this.application = application;
		this.remoteAddress = new InetSocketAddress(remoteAddress, remotePort);
		this.localAddress = new InetSocketAddress(localAddress,localPort);
		this.serverId = serverId ;
		this.identity = identity;
	}
	
	@Override
	public String getServerId() {
		return this.serverId;
	}

	@Override
	public int getIdentity() {
		return this.identity;
	}
	
	@Override
	public boolean isConnected() {
		if (status == CONNECTED) {
			return true;
		}
		return false;
	}

	@Override
	public InetSocketAddress getRemoteAddress() {
		return remoteAddress;
	}

	@Override
	public Object getAttribute(String key) {
		return attributes.get(key);
	}

	@Override
	public void setAttribute(String key, Object value) {
		if (value == null) { 
			attributes.remove(key);
		} else {
			attributes.put(key, value);
		}
	}

	@Override
	public boolean contains(String key) {
		return attributes.containsKey(key);
	}

	@Override
	public void removeAttribute(String key) {
		this.removeAttribute(key);
	}

	@Override
	public AppConf getConf() {
		return null;
	}

	@Override
	public InetSocketAddress getLocalAddress() {
		return localAddress;
	}

	@Override
	public ChannelHandler getChannelHandler() {
		return null;
	}

	@Override
	public void send(Object message) throws RemoteException {
		LocalSession localSession = LocalSessionMgr.getInstance().getLocalSession(serverId);
		if (localSession != null) {
			localSession.send(this.identity, message);
		}else {
			//TODO 
			LOGGER.warn("Failed to send message to client,cause :Could not found remote server {}",serverId);
		}
	}

	@Override
	public void close() {
		this.status = STATUS_CLOSED;
		
		if (listener != null) {
			listener.onSessionClosed(this);
		}
	}

	@Override
	public void close(int timeout) {
		close();
	}

	@Override
	public boolean isClosed() {
		if (status == STATUS_CLOSED) {
			return true;
		}
		return false;
	}

	@Override
	public void setlistener(SessionCloseListener listener) {
		if(this.listener != null) {
			throw new IllegalArgumentException("Failed to set up listner,cause :listener already set up");
		}
		
		this.listener = listener ;
	}

	public String getClientType() {
		return clientType;
	}

	public void setClientType(String clientType) {
		this.clientType = clientType;
	}
}

